package com.hc.util.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author fenfei
 */
public class SocketUtil {

    ServerSocket serverS;
    SocketListener lstn;

    /**
     * Should not be null
     * @param lstn 
     */
    public void setListener(SocketListener lstn) {
        this.lstn = lstn;
      //  System.out.println(this.lstn);
    }

    public void serve(String port) throws IOException, NumberFormatException {
        serverS = new ServerSocket(Integer.parseInt(port));
        lstn.serverStarted(serverS);
        new Thread() {

            public void run() {
                try {
                    while (true) {
                        Socket socket = serverS.accept();
                        System.out.println("A ceonnection is received by the server:"+socket);
                        connectionEstablished(socket);
                    }
                } catch (IOException e) {
                    System.out.println("Exception when the server socket is accepting: "+e);
                }
                lstn.serverStopped();
                serverS = null;
            }
        }.start();
    }

    public void stopServer() throws IOException {
        serverS.close();
        lstn.serverStopped();
        serverS = null;
    }

    public boolean isServerRunning() {
        return serverS != null;
    }

    public void connect(String ip, String port) throws UnknownHostException, IOException {
        Socket socket = new Socket(ip, Integer.parseInt(port));
        connectionEstablished(socket);
    }

    public void send(String msg, Socket socket) throws IOException {
          OutputStreamWriter w = new OutputStreamWriter(socket.getOutputStream());
          w.write(msg+"\n");
          w.flush();
    
    }

    private void connectionEstablished(Socket socket) {
        lstn.connectionEstablished(socket);
        new ReceiveThread(socket).start();
    }

    class ReceiveThread extends Thread {
        Socket socket;
        public ReceiveThread(Socket socket) {
            this.socket=socket;
        }

        public void run() {
            try {
                BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream(),"GBK"));
                
                String l;
                while ((l = r.readLine()) != null) {
                    System.out.println("received msg:"+l);
                    lstn.onMessage(l, socket);
                }
            } catch (Exception e) {
                System.err.println("Error receiving message"+e);
                e.printStackTrace();
            }
            lstn.connectionClosed(socket);
        }
    };
    public static List getIPv4s(){
        List ips=new ArrayList();
         Enumeration<NetworkInterface> ns=null;
        try {
            ns = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException ex) {
            Logger.getLogger(SocketUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        while(ns.hasMoreElements()){
           ips.add(ns.nextElement().getInterfaceAddresses().get(1).getAddress().getHostAddress());
            //System.out.println("InterfaceAddresses:"+ni.getInterfaceAddresses());
        }
        return ips;
    }
}
